﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Common.Utils;
using DynamicData;
using Newtonsoft.Json;
using Org.BouncyCastle.Math.EC.Rfc7748;
using ReactiveUI.Fody.Helpers;

namespace Common.ViewModels
{
    public class 主通道调度 : BaseViewModel
    {

        /// <summary>
        /// 调度用的小车
        /// </summary>
        [Reactive] public Car Car { get; set; }

        /// <summary>
        /// 上料工位
        /// </summary>
        [Reactive] public WorkStation 上料WorkStation { get; set; } = new WorkStation();

        /// <summary>
        /// 下料工位
        /// </summary>
        [Reactive] public WorkStation 下料WorkStation { get; set; } = new WorkStation();

        public readonly object m_Lock工件 = new object();

        public List<工件> Lis工件 = new List<工件>();

        [JsonIgnore]
        public int 进入工件数量 { get; set; } = 0;

        /// <summary>
        /// 主通道
        /// </summary>
        [Reactive] public PassVM PassVM { get; set; }



        /// <summary>
        /// 处理(这里采用单线程)
        /// </summary>
        public void Deal()
        {
            while (true)
            {
                IEnumerable<工件> 待处理工件s;
                lock (m_Lock工件)
                {
                    //整理出待处理的工件
                    待处理工件s = Lis工件.Where(x => x.IsWaitMove);
                }

                //没有待处理工件,原地休息
                if (待处理工件s.Count() == 0)
                {
                    Thread.Sleep(100);
                    continue;
                }

                // 处理最近的待处理工件
                工件 待处理工件 = Get工件(待处理工件s);

                //将工件挪到小车上面(并且等待移动完成)
                double posFrom = GetPos(待处理工件.CurrentWorkStation);

                Car.MoveStation(posFrom);
                //机械手提取工件
                Thread.Sleep(ProductLine.Instance.机械手提取工件时间);
                Car.Have工件 = true;//让小车拥有工件
                Car.工件 = 待处理工件;
                //移除工件
                待处理工件.CurrentWorkStation.Remove工件();
                double posTo = GetPos(待处理工件.NextWorkStation);
                Car.MoveStation(posTo);
                Thread.Sleep(ProductLine.Instance.机械手提取工件时间);//机械手提取工件
                Car.Have工件 = false;
                Car.工件 = null;
                //重置移动之前的Lock
                lock (m_Lock工件)
                {
                    //解锁工件
                    待处理工件.CurrentWorkStation.IsLock = false;
                    //下一个站点新增工件
                    待处理工件.NextWorkStation.Add工件(待处理工件);
                    Lis工件.Remove(待处理工件);//移除待处理工件
                    待处理工件.IsWaitMove=false;
                }
                //小车处理一台马上去另外一台 或者歇着
            }
        }

        public double GetPos(WorkStation workStation)
        {
            if (workStation.池子 == null)
            {
                return GetPos(workStation.Station);
            }

            return workStation.池子.PointStart.Y - PassVM.LineRigidBody.PointStartBase.Y;
        }

        /// <summary>
        /// 处理上料工位,上料的工位定时上料()
        /// </summary>
        /// <param name="workStation"></param>
        public void Deal上料Station(WorkStation workStation)
        {
            while (true)
            {
                try
                {
                    片区.DealContinueRun(workStation);
                    工件 工件 = workStation.当前工件;
                    //有工件 等待工件没有
                    if (工件 != null && 工件.IsWaitMove)
                    {
                        Thread.Sleep(100);
                        continue;
                    }

                    //if (工件.IsWaitMove)
                    //{
                    //    Thread.Sleep(100);
                    //    continue;
                    //}

                    //没有工件 创建工件
                    工件 = Create();
                    workStation.当前工件 = 工件;
                    workStation.是否有料 = true;
                    工件.StartTime=DateTime.Now;
                    //创建完工件之后 选择移动到片区

                    MoveNext片区(workStation, 工件);
                    //return;
                    Thread.Sleep(100);//休眠一下
                }
                catch (Exception e)
                {

                }
            }
        }

        /// <summary>
        /// 处理下料池子
        /// </summary>
        /// <param name="workStation"></param>
        public void Deal下料WorkStation(WorkStation workStation)
        {
            while (true)
            {
                try
                {
                    片区.DealContinueRun(workStation);
                    工件 工件 = workStation.当前工件;
                    //有工件 等待工件没有
                    if (工件 == null)
                    {
                        Thread.Sleep(100);
                        continue;
                    }

                    //移除工件,并等待下一个工件
                    ProductLine.Instance.主通道调度.Remove(工件);
                    workStation.Remove工件();//移除工件
                    lock (m_Lock工件)
                    {
                        workStation.IsLock = false;
                    }



                }
                catch (Exception e)
                {

                }
            }
        }

        /// <summary>
        /// 跨区调度(跨区调度,将这个系统弄到主通道)
        /// </summary>
        /// <param name="workStation"></param>
        /// <param name="工件"></param>
        public void MoveNext片区(WorkStation workStation, 工件 工件)
        {
            //判断工件下一个站点在哪个片区
            //遍历片区
            if (工件.Step == 工件.WorkStations.Count)
            {
                //移动到下料
                while (true)
                {
                    Thread.Sleep(100);
                    lock (m_Lock工件)
                    {
                        if (this.下料WorkStation.IsLock)
                        {
                            continue;
                        }
                        else
                        {
                            this.下料WorkStation.IsLock = true;
                            break;
                        }
                    }
                }
                工件.IsWaitMove = true;
                //工件.StartTime = DateTime.Now;
                工件.NextWorkStation = this.下料WorkStation;
                工件.NextStation = this.下料WorkStation.Station;
                ProductLine.Instance.主通道调度.Add(工件);//将工件纳入主通道调度
                return;
            }

            工位类型 gwlx工位类型 = 工件.WorkStations[工件.Step];
            片区 next片区 = null;
            //找到片区
            bool haveFind = false;
            foreach (var item in ProductLine.Instance.片区s)
            {
                foreach (var cz池子 in item.池子s)
                {
                    if (cz池子.工位类型 == null)
                    {
                        continue;
                    }

                    if (cz池子.工位类型.Name == gwlx工位类型.Name)
                    {
                        next片区 = item;
                        haveFind = true;
                        break;
                    }
                }

                if (haveFind)
                {
                    break;
                }
            }

            //找到对应池子
            if (!haveFind)
            {
                MessageAggregator<ErrorMsg>.Publish($"没有找到工件 {工件.Name}  的片区有相应的工位类型 {gwlx工位类型.Name}  系统中止");
                return;
            }


            bool haveFindWorkStation = false;
            WorkStation nextWorkStation = null;
            while (true)
            {
                foreach (var cz池子 in next片区.池子s)
                {
                    //if (cz池子.工位类型.Name != gwlx工位类型.Name)
                    //{
                    //    continue;
                    //}

                    //需要先经过上料池子
                    if (cz池子.池子类型 != 池子类型.上料池子)
                    {
                        continue;
                    }

                    foreach (var item in cz池子.Works)
                    {
                        lock (ProductLine.Instance.主通道调度.m_Lock工件)
                        {
                            if (item.IsLock)
                            {
                                continue;
                            }
                            else
                            {
                                item.IsLock = true;
                                nextWorkStation = item;
                                haveFindWorkStation = true;
                                break;
                            }
                        }
                    }
                }

                if (haveFindWorkStation)
                {
                    break;
                }

                Thread.Sleep(100);
            }

            //这里置位移动状态,避免重复。
            工件.IsWaitMove = true;
            //工件.StartTime = DateTime.Now;
            工件.NextWorkStation = nextWorkStation;
            工件.NextStation = nextWorkStation.Station;
            ProductLine.Instance.主通道调度.Add(工件);//将工件纳入主通道调度
        }

        /// <summary>
        /// 获取位置
        /// </summary>
        /// <param name="station"></param>
        /// <returns></returns>
        public double GetPos(Station station)
        {
            return station.Point3D.Y - PassVM.LineRigidBody.PointStartBase.Y;
        }

        public static 工件 Get工件(IEnumerable<工件> 待处理工件s)
        {
            工件 ret工件 = 待处理工件s.First();

            foreach (工件 待处理工件 in 待处理工件s)
            {
                if (ret工件.StartTime > 待处理工件.StartTime)
                {
                    ret工件 = 待处理工件;
                }
            }

            return ret工件;
        }

        /// <summary>
        /// 添加工件(添加工件信息)
        /// </summary>
        /// <param name="工件"></param>
        public void Add(工件 工件)
        {
            lock (m_Lock工件)
            {
                Lis工件.Add(工件);
            }
        }

        public void Remove(工件 工件)
        {
            lock (m_Lock工件)
            {
                Lis工件.Remove(工件);
            }
        }


        /// <summary>
        /// 创建工件(模拟使用)
        /// </summary>
        /// <returns></returns>
        public 工件 Create()
        {
            //this.进入工件数量++;
            工件 工件 = new 工件()
            {
                Name = $"工件{this.进入工件数量}"
            };
            工件.Num = ++this.进入工件数量;
            工件.配方 = ProductLine.Instance.Select配方;//配方
            工件.WorkStations = Get工位类型s(工件.配方);//配方细化
            工件.CurrentWorkStation = this.上料WorkStation;
            工件.CurrentStation = this.上料WorkStation.Station;
            return 工件;
        }

        public List<工位类型> Get工位类型s(配方 pf)
        {
            List<工位类型> ret = new();
            foreach (工位类型 工位类型 in pf.工位类型s)
            {
                if (工位类型 is 配方 子配方)
                {
                    ret.AddRange(Get工位类型s(子配方));
                }
                else
                {
                    ret.Add(工位类型);
                }
            }
            return ret;
        }

        /// <summary>
        /// 添加工件配方
        /// </summary>
        public void Add工位类型()
        {

        }


    }
}
